<?php
/**
 * Abstract.php - 27 Jan 2009
 * 
 * @author Kevin Breed
 */
 
abstract class KB_Bootstrap_Abstract
{	
	/**
	 * @var object	Environment class
	 */
	public $env;
	
	
	/**
	 * @var string	The name of the config file including extension
	 */
	public $configFileName = 'config.ini';
	
	/**
	 * @var array 	An one dimensional array with namespaces to register with 
	 *				Zend's autoloader
	 */
	protected $_autoLoaderNameSpaces = array();
	
	/**
	 * @var string	The name of the front controller class
	 */
	protected $_frontControllerClassName = 'Zend_Controller_Front';
	
	/**
	 * @var object	Front Contoller instance
	 */
	protected $_frontContoller;
	
	
	/**
	 * @var KB_Config	Config instance
	 */
	protected $_config;
	
	
	/*********************/
	/* GETTERS & SETTERS */
	/*********************/
	
	/**
	 * Set the front controller to use
	 * 
	 * @param	string	$frontControllerName	The name of the front controller
	 * 											class
	 * @return	void
	 */
	public function setFrontController ( $frontControllerName )
	{
		$this->_frontControllerClassName = $frontControllerName;
	}
	
	/**
	 * Returns the complete path to the application config file
	 * 
	 * @return	string	The full path to the application config file
	 */
	public function getApplicationConfigFile ()
	{
		return $this->env->applicationConfigPath . '/' . $this->configFileName;
	}
	
	/**
	 * Returns the complete path to the library config file
	 * 
	 * @return	string	The full path to the library config file
	 */
	public function getLibraryConfigFile ()
	{
		return $this->env->libraryConfigPath . '/' . $this->configFileName;
	}
	
	
	/*********************/
	/* MACHINERY HANDLES */
	/*********************/
	
	public function addNameSpace( $ns )
	{
		$this->_autoLoaderNameSpaces[] = $ns;
	}
	
	public function removeNameSpace( $ns )
	{
		$key = array_search( $ns, $this->_autoLoaderNameSpaces );
		unset( $this->_autoLoaderNameSpaces[ $ns ] );
	}
		
	/**
	 * I had to get up to get down to start all over again
	 * Head on down to the basement and shout
	 * Kick those white mice and black dogs out
	 * Kick those white mice and baboons out
	 * Kick those baboons and other motherfuckers out
	 * And get it on get it on get it on
	 * On the day that you got born
	 */
	public function getItOn ()
	{		
		$this->_setUpIncludePath();
		$this->_setUpLoader();
		$this->_setUpConfig();
		$this->_setUpFrontController();
		$this->_setUpErrorReporting();		
		$this->_setupControllers();
		$this->_setupViews();
		$this->_setupLayout();
		$this->_setupModels();
		$this->_setupDb();
		$this->_setupLocale();
		
		// RUN!!!
		$this->_frontController->dispatch(); 
	}
	
	
	/*************/
	/* MACHINERY */
	/*************/
	
	/**
	 * Constructor
	 * 
	 * @param	string	$projectDirName	The name of the project directory
	 * @param	string	$libraryDirName	The name of the library directory
	 */
	public function __construct () 
	{
		// do nothing untill we get it on, only initialise bootstrap
		$this->_initConfigFileName();
		$this->_initEnvironment();
	}
	
	
	// ABSTRACT INIT //
	
	abstract protected function _initConfigFileName ();
	abstract protected function _initEnvironment ();
	
	
	// SETUP //
	
	/**
	 * Set the include path(s)
	 */
	protected function _setUpIncludePath ()
	{
		set_include_path
		( 
			get_include_path() 			. PATH_SEPARATOR .
			$this->env->applicationPath . PATH_SEPARATOR
		);
	}
	
	/**
	 * Zend loader init
	 */
	protected function _setUpLoader ()
	{
		require_once( 'Zend/Loader/Autoloader.php' );
		
		// Auto load classfiles from here on
		$al = Zend_Loader_Autoloader::getInstance();
		
		// Since this is a KB_ bootstrap class, we can be kindly enough to 
		// register the KB_ namespace as well
		$this->addNameSpace( 'KB_' );
		
		foreach ( $this->_autoLoaderNameSpaces as $ns )
			$al->registerNamespace( $ns );
	}
	
	/**
	 * Load the required config settings and saves them into the registry
	 */
	protected function _setUpConfig ()
	{
		$confArray = 	
		array
		( 
			'paths' => 
				array
				( 
					'docRoot'				=> $this->env->docRoot,
					'projectDirName'		=> $this->env->projectDirName,
					'applicationDirName'	=> $this->env->applicationDirName,
					'applicationDir' 		=> $this->env->applicationPath,
					'libraryDir'			=> $this->env->libraryPath,
					'appConfigDir'			=> $this->env->applicationConfigPath,
					'libConfigDir'			=> $this->env->libraryConfigPath
				) 
		);
		
		$conf = new KB_Config( $confArray, true );
		
		// Get library config
		$libConf = new Zend_Config_Ini( $this->getLibraryConfigFile() );
		$conf->mergeFirst( $libConf );
		
		// Get application config
		
		if ( file_exists( $this->getApplicationConfigFile() ) )
		{
			$appConf = new Zend_Config_Ini( $this->getApplicationConfigFile() );
			$conf->mergeFirst( $appConf );
		}
		
		$conf->setReadOnly();
		
		// Save config into config manager
		$confMan = KB_Config_Manager::getInstance();
		$confMan->addConfigObject( 'default', $conf );
		
		$this->_config = $conf;
	}
	
	/**
	 * Set the front controller instance.
	 */
	protected function _setUpFrontController ()
	{
		$this->_frontController = call_user_func
		( 
			array( $this->_frontControllerClassName, 'getInstance' ) 
		);
	}
	
	/**
	 * Error reporting setup.
	 */
	protected function _setUpErrorReporting ()
	{
		$er = $this->_config->errorHandling->get( 'errorReporting', 	E_ALL|E_STRICT );
		$de = $this->_config->errorHandling->get( 'displayErrors', 		1 );
		$te = $this->_config->errorHandling->get( 'throwExceptions', 	true );
				
		error_reporting( $er );
		ini_set( 'display_errors', $de );
		$this->_frontController->throwExceptions( $te );
	}
	
	/**
	 * Controller init
	 * 
	 * @return void
	 */
	protected function _setUpControllers ()
	{
		$cd = $this->_config->zendpaths->get( 'controllerDir', false );		
		if ( $cd ) 	$this->_frontController->setControllerDirectory( $cd );
	}
	
	/**
	 * Layout init
	 * 
	 * @return void
	 */
	protected function _setUpLayout ()
	{
		$ld = $this->_config->zendpaths->get( 'layoutDir', false );
		if ( $ld ) Zend_Layout::startMvc( array( 'layoutPath' => $ld ) );
	}
	
	/**
	 * View init
	 * 
	 * @return void
	 */
	protected function _setUpViews ()
	{
		$view = new Zend_View();
		
		// view dir
		$vd = $this->_config->zendpaths->get( 'viewDir', false );
		if ( $vd ) $view->setBasePath( $vd );
		
		// script dir
		$sd = $this->_config->zendpaths->get( 'scriptDir', false );
		if ( $sd ) $view->setScriptPath( $sd );
		
		// helper dir
		$hd = $this->_config->zendpaths->get( 'helperDir', false );
		if ( $hd ) $view->setHelperPath( $hd );
		
		// filter dir
		$fd = $this->_config->zendpaths->get( 'filterDir', false );
		if ( $fd ) $view->setFilterPath( $fd );
		
		if ( $vd || $sd )
		{
			$vr = Zend_Controller_Action_HelperBroker::getStaticHelper( 'ViewRenderer' );
			$vr->setView( $view );
		}
	}
	
	/**
	 * Locale init
	 * 
	 * @return void
	 */
	protected function _setUpLocale ()
	{
		$dtz = $this->_config->locale->get( 'default_timezone', false );
		if ( $dtz ) date_default_timezone_set( $dtz );
	}
	
	/**
	 * Models init
	 * 
	 * @return void
	 */
	protected function _setUpModels ()
	{
		$md = $this->_config->zendpaths->get( 'modelDir', false );
		if ( $md ) set_include_path( get_include_path() . PATH_SEPARATOR . $md );
	}
	
	/**
	 * Database init
	 * 
	 * @return void
	 */
	protected function _setUpDb ()
	{
		if ( $this->_config->database->params->get( 'dbname', false ) )
		{
			$db = Zend_Db::factory( $this->_config->database );		
			Zend_Db_Table::setDefaultAdapter( $db );
		}
	}
}

?>
